package com.wanhe.vip.api;

import android.content.Context;
import android.support.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.orhanobut.logger.Logger;
import com.wanhe.vip.api.bean.BaseResponse;
import com.wanhe.vip.api.bean.CardInfo;
import com.wanhe.vip.api.bean.PageResponse;
import com.wanhe.vip.api.bean.VipCard;
import com.wanhe.vip.api.bean.VipCoupon;
import com.wanhe.vip.api.bean.VipPay;
import com.wanhe.vip.utils.NetUtil;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by XieZaiWei on 2017/4/11.
 * 整个网络通信服务的启动控制，必须先调用初始化函数才能正常使用网络通信接口
 */
public class RetrofitService {

	private static final String HEAD_LINE_NEWS = "T1348647909107";
	//设缓存有效期为1天
	static final long CACHE_STALE_SEC = 60 * 60 * 24 * 1;
	//查询缓存的Cache-Control设置，为if-only-cache时只查询缓存而不会请求服务器，max-stale可以配合设置缓存失效时间
	private static final String CACHE_CONTROL_CACHE = "only-if-cached, max-stale=" + CACHE_STALE_SEC;
	//查询网络的Cache-Control设置
	//(假如请求了服务器并在a时刻返回响应结果，则在max-age规定的秒数内，浏览器将不会发送对应的请求到服务器，数据由缓存直接返回)
	static final String CACHE_CONTROL_NETWORK = "Cache-Control: public, max-age=3600";
	// 避免出现 HTTP 403 Forbidden，参考：http://stackoverflow.com/questions/13670692/403-forbidden-with-java-but-not-web-browser
	static final String AVOID_HTTP403_FORBIDDEN = "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11";

	private static final String CALL_RING_HOST = "http://10.0.1.193:8022/";

	private static VipApi vipApi;
	// 递增页码
	private static final int INCREASE_PAGE = 20;

	private static Context mContext;


	private RetrofitService() {
		throw new AssertionError();
	}

	/**
	 * 初始化网络通信服务
	 */
	public static void init(Context context) {
		mContext = context;
		// 指定缓存路径,缓存大小100Mb
		Cache cache = new Cache(new File(context.getCacheDir(), "HttpCache"), 1024 * 1024 * 100);
		OkHttpClient.Builder builder = new OkHttpClient.Builder().cache(cache)
				.retryOnConnectionFailure(true)
				.addInterceptor(sLoggingInterceptor)
				.addInterceptor(sRewriteCacheControlInterceptor)
				.addNetworkInterceptor(sRewriteCacheControlInterceptor)
				.connectTimeout(10, TimeUnit.SECONDS);

		//		if (BuildConfig.DEBUG) {
		//			// Log信息拦截器
		//			HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
		//			loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//这里可以选择拦截级别
		//			//设置 Debug Log 模式
		//			builder.addInterceptor(loggingInterceptor);
		//		}

		OkHttpClient okHttpClient = builder.build();

		Retrofit retrofit = new Retrofit.Builder()
				.client(okHttpClient)
				.addConverterFactory(GsonConverterFactory.create())
				.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
				.baseUrl(CALL_RING_HOST)
				.build();
		vipApi = retrofit.create(VipApi.class);

	}

	/**
	 * 云端响应头拦截器，用来配置缓存策略
	 * Dangerous interceptor that rewrites the server's cache-control header.
	 */
	private static final Interceptor sRewriteCacheControlInterceptor = new Interceptor() {

		@Override
		public Response intercept(Chain chain) throws IOException {
			Request request = chain.request();
			if (!NetUtil.isNetworkAvailable(mContext)) {
				request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
				Logger.e("no network");
			}
			Response originalResponse = chain.proceed(request);

			if (NetUtil.isNetworkAvailable(mContext)) {
				//有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
				String cacheControl = request.cacheControl().toString();
				return originalResponse.newBuilder()
						.header("Cache-Control", cacheControl)
						.removeHeader("Pragma")
						.build();
			} else {
				return originalResponse.newBuilder()
						.header("Cache-Control", "public, " + CACHE_CONTROL_CACHE)
						.removeHeader("Pragma")
						.build();
			}
		}
	};

	/**
	 * 打印返回的json数据拦截器
	 */
	private static final Interceptor sLoggingInterceptor = new Interceptor() {

		@Override
		public Response intercept(Chain chain) throws IOException {
			final Request request = chain.request();
			long t1 = System.nanoTime();//请求发起的时间
			Buffer requestBuffer = new Buffer();
			if (request.body() != null) {
				request.body().writeTo(requestBuffer);
			} else {
				Logger.d("CallRing", "request.body() == null");
			}
			//打印url信息
			Logger.w(request.url() + (request.body() != null ? "?" + _parseParams(request.body(), requestBuffer) : ""));
			long t2 = System.nanoTime();//收到响应的时间
			final Response response = chain.proceed(request);
			ResponseBody responseBody = response.peekBody(1024 * 1024);
			Logger.w(String.format("接收响应: [%s] %n时间:%.1fms%n%s返回data:%s",
					response.request().url(),
					(t2 - t1) / 1e6d,
					response.headers(),
					responseBody.string()));
			return response;
		}
	};

	@NonNull
	private static String _parseParams(RequestBody body, Buffer requestBuffer) throws UnsupportedEncodingException {
		if (body.contentType() != null && !body.contentType().toString().contains("multipart")) {
			return URLDecoder.decode(requestBuffer.readUtf8(), "UTF-8");
		}
		return "null";
	}

	/************************************ 转换器 *******************************************/

	private static <T> Observable<T> flatMapRsponse(Observable<BaseResponse<T>> response) {
		return response.flatMap(new Function<BaseResponse<T>, ObservableSource<T>>() {
			@Override
			public ObservableSource<T> apply(BaseResponse<T> tBaseResponse)  {
				if ("0".equals(tBaseResponse.errorCode)) {//成功
					return Observable.just(tBaseResponse.result);
				} else {//失败
					//可以添加统一错误提示
					return Observable.just(tBaseResponse.result);
				}
			}
		});
	}

	/************************************ API *******************************************/

	/**
	 * 获取会员所拥有的卡列表
	 *
	 * @param phone
	 */
	public static Observable<PageResponse<VipCard>> getVipCardList(String phone) {
		JSONObject param = new JSONObject();
		try {
			param.put("op", "GetMemberCards");
			param.put("phoneNo", phone);
		} catch (Exception e) {

		}
		HashMap<String, String> map = new HashMap();
		map.put("paramJsonStr", param.toString());

		return flatMapRsponse(vipApi.getCardList(map)
				.subscribeOn(Schedulers.io())
				.unsubscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread()));
	}

	/**
	 * 获取单张会员卡的信息
	 * @param cardNo
	 * @return
	 */
	public static Observable<CardInfo> getCardInfo(String cardNo) {
		JSONObject param = new JSONObject();
		try {
			param.put("op", "GetMemberCardInfo");
			param.put("cardNo", cardNo);
		} catch (Exception e) {

		}
		HashMap<String, String> map = new HashMap();
		map.put("paramJsonStr", param.toString());

		return flatMapRsponse(vipApi.getCardInfo(map)
				.subscribeOn(Schedulers.io())
				.unsubscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread()));
	}

	/**
	 * 预消费
	 * @param cardId
	 * @param billAmount
	 * @param prePay
	 * @param cash
	 * @param vipCouponModel
	 * @return
	 */
	public static Observable<JsonObject> preConsume(String cardId, String billAmount, String prePay, String cash, VipCoupon vipCouponModel) {
		//要转成分
		billAmount = String.valueOf(Double.valueOf(billAmount) * 100);
		if ("".equals(prePay)) {
			prePay = "0";
		} else {
			prePay = String.valueOf(Double.valueOf(prePay) * 100);
		}
		if ("".equals(cash)) {
			cash = "0";
		} else {
			cash = String.valueOf(Double.valueOf(cash) * 100);
		}
		VipPay model = new VipPay();
		model.setOp("PreConsume");
		model.setCardId(cardId);
		model.setCardPwd("");
		model.setTransMoney(billAmount);//交易总金额
		model.setTransPrepay(prePay);//使用预存额
		model.setTransPoint("0");//使用积分
		model.setTransCash(cash);//使用现金
		model.setNeedMobileCode("1");
		model.setNeedWechatCode("0");

		if (vipCouponModel != null) {
			switch (vipCouponModel.getCouponType()) {
				case "cashCoupon"://现金优惠券
					//要转成分
					String money = String.valueOf(Double.valueOf(vipCouponModel.getMoney()) * 100);
					model.setTransCoupon(money);//使用代金券
					model.setTransCouponInfo(vipCouponModel.getCouponId());//使用代金券的id串
					model.setTransDiscountCoupon("");//使用折扣抵现金额
					model.setTransDiscountCouponInfo("");//使用折扣券的id串
					model.setTransGiftCouponInfo("");//使用礼品券的id串
					break;

				case "discountCoupon"://折扣优惠券
					model.setTransCoupon("0");//使用代金券
					model.setTransCouponInfo("");//使用代金券的id串
					model.setTransDiscountCoupon(vipCouponModel.getDiscount());//使用折扣抵现金额
					model.setTransDiscountCouponInfo(vipCouponModel.getCouponId());//使用折扣券的id串
					model.setTransGiftCouponInfo("");//使用礼品券的id串
					break;

				case "giftCoupon"://礼品券
					model.setTransCoupon("0");//使用代金券
					model.setTransCouponInfo("");//使用代金券的id串
					model.setTransDiscountCoupon("");//使用折扣抵现金额
					model.setTransDiscountCouponInfo("");//使用折扣券的id串
					model.setTransGiftCouponInfo(vipCouponModel.getCouponId());//使用礼品券的id串
					break;

				default:
					break;
			}

		} else {
			model.setTransCoupon("0");//使用代金券
			model.setTransCouponInfo("");//使用代金券的id串
			model.setTransDiscountCoupon("");//使用折扣抵现金额
			model.setTransDiscountCouponInfo("");//使用折扣券的id串
			model.setTransGiftCouponInfo("");//使用礼品券的id串
		}
		HashMap<String, String> map = new HashMap();
		try {
			String param = new String(new Gson().toJson(model).getBytes("UTF-8"), "UTF-8");
			map.put("paramJsonStr", param);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return flatMapRsponse(vipApi.preConsume(map)
				.subscribeOn(Schedulers.io())
				.unsubscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread()));
	}

	public static Observable<JsonObject> doConsume(String cardId, String billAmount, String prePay, String cash, VipCoupon vipCouponModel, String verifyCode) {
		//要转成分
		billAmount = String.valueOf(Double.valueOf(billAmount) * 100);
		if ("".equals(prePay)) {
			prePay = "0";
		} else {
			prePay = String.valueOf(Double.valueOf(prePay) * 100);
		}
		if ("".equals(cash)) {
			cash = "0";
		} else {
			cash = String.valueOf(Double.valueOf(cash) * 100);
		}
		VipPay model = new VipPay();
		model.setOp("DoConsume");
		model.setCardId(cardId);
		model.setCardPwd("");
		model.setTransMoney(billAmount);//交易总金额
		model.setTransPrepay(prePay);//使用预存额
		model.setTransPoint("0");//使用积分
		model.setTransCash(cash);//使用现金

		if (vipCouponModel != null) {
			switch (vipCouponModel.getCouponType()) {
				case "cashCoupon"://现金优惠券
					//要转成分
					String money = String.valueOf(Double.valueOf(vipCouponModel.getMoney()) * 100);
					model.setTransCoupon(money);//使用代金券
					model.setTransCouponInfo(vipCouponModel.getCouponId());//使用代金券的id串
					model.setTransDiscountCoupon("");//使用折扣抵现金额
					model.setTransDiscountCouponInfo("");//使用折扣券的id串
					model.setTransGiftCouponInfo("");//使用礼品券的id串
					break;

				case "discountCoupon"://折扣优惠券
					model.setTransCoupon("0");//使用代金券
					model.setTransCouponInfo("");//使用代金券的id串
					model.setTransDiscountCoupon(vipCouponModel.getDiscount());//使用折扣抵现金额
					model.setTransDiscountCouponInfo(vipCouponModel.getCouponId());//使用折扣券的id串
					model.setTransGiftCouponInfo("");//使用礼品券的id串
					break;

				case "giftCoupon"://礼品券
					model.setTransCoupon("0");//使用代金券
					model.setTransCouponInfo("");//使用代金券的id串
					model.setTransDiscountCoupon("");//使用折扣抵现金额
					model.setTransDiscountCouponInfo("");//使用折扣券的id串
					model.setTransGiftCouponInfo(vipCouponModel.getCouponId());//使用礼品券的id串
					break;

				default:
					break;
			}

		} else {
			model.setTransCoupon("0");//使用代金券
			model.setTransCouponInfo("");//使用代金券的id串
			model.setTransDiscountCoupon("");//使用折扣抵现金额
			model.setTransDiscountCouponInfo("");//使用折扣券的id串
			model.setTransGiftCouponInfo("");//使用礼品券的id串
		}
		model.setNeedMobileCode("1");
		model.setNeedWechatCode("0");
		model.setMobileCode(verifyCode);
		model.setTakeoutType("dinein");

		HashMap<String, String> map = new HashMap();
		try {
			String param = new String(new Gson().toJson(model).getBytes("UTF-8"), "UTF-8");
			map.put("paramJsonStr", param);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return flatMapRsponse(vipApi.doConsume(map)
				.subscribeOn(Schedulers.io())
				.unsubscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread()));
	}

}
